package pt.inescid.components.policyengine.heimdall.pdp.base;

import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.contact.Outbound;
import pt.inescid.components.policyengine.heimdall.pap.base.SubPolicyDefinition;
import pt.inescid.components.policyengine.heimdall.pdp.PolicyDecision;
import pt.inescid.components.policyengine.heimdall.pip.NodeInfo;

public class SubPolicyInstance extends SimpleInstance {

	private SubPolicyDefinition definition = null;
	private DomainInstance domain = null;
	private PolicyInstance policy = null;
	
	//  ----------------------------------------------------------
//  ------------------------   constructor   ------------------------
//  ----------------------------------------------------------
	public SubPolicyInstance(SubPolicyDefinition definition, 
			ModelInstance currentModel,
			PolicyInstance currentPolicy) {
		super(definition, currentPolicy);
		domain = new DomainInstance(definition.getDomain());
		
		boolean foundLocalNode = false;
		Vector allNodes = domain.getNodes();
		
		NodeInfo currentNode = null;
		for (int i = 0; i < allNodes.size(); i++) {
			currentNode = (NodeInfo) allNodes.elementAt(i);
			
			if (currentNode.isLocal()) {
				foundLocalNode = true;
				i = allNodes.size();
			}
		}
		
		if (foundLocalNode) {
			this.policy = new PolicyInstance(
					currentModel.getDefinition().getPolicy(
							definition.getValue()), 
					currentModel);
		}
		else {
			this.policy = null;
		}
			
		this.definition = definition;
	}

	//  ----------------------------------------------------------
//  ------------------------   evaluate   ------------------------
//  ----------------------------------------------------------
	public Object evaluate(ModelInstance currentModel, boolean onlyCached) {
		
		if (decision.getStatus() == PolicyDecision.STATUS_UNDEFINED) {
			
			Vector allNodes = domain.getNodes();
			
			NodeInfo currentNode = null;
			for (int i = 0; i < allNodes.size(); i++) {
				currentNode = (NodeInfo) allNodes.elementAt(i);
				
				if (currentNode.isLocal()) {
					try {
						policy.evaluate(currentModel, onlyCached);
						decision = policy.getDecision();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				else {
					Outbound.requestRemoteEvaluation(
							currentModel, definition.getValue(), 
							currentNode);
					decision.setStatus(PolicyDecision.STATUS_WAITING_INFO);
				}
			}
		}

		return (Boolean.TRUE);
	};


//  ----------------------------------------------------------
//  ------------------------   toString   ------------------------
//  ----------------------------------------------------------
	public String toString() {
		String result = "";
		
		result += "Rule " + definition.getFunction() + "\n";
		result += "\tDomain:\n" + domain + "\n";
		result += "\tPolicy:\n" + policy + "\n";
		
		return (super.toString() + result);
	}


	public DomainInstance getDomain() {
		return domain;
	}

	public PolicyInstance getPolicy() {
		return policy;
	}

	public void setDomain(DomainInstance domain) {
		this.domain = domain;
	}

	public void setPolicy(PolicyInstance policy) {
		this.policy = policy;
	}

}; // SubPolicyExpression
